package com.xrui.hbase;

import com.google.common.base.CharMatcher;
import com.google.common.base.Preconditions;
import com.sun.istack.NotNull;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public final class TableName {
    static char DEFAULT_SEPARATOR = '_';
    private String mPrefix;
    private String mNamespace;
    private Character mSeparator;
    private String mIdentifier;
    private String mName;

    public TableName(@Nullable String namespace, @Nullable String prefix, Character separator, @NotNull String identifier) {
        // Make sure the table identifier is not empty
        Preconditions.checkArgument(!identifier.isEmpty());
        if (prefix != null) {
            // Separator should not null when prefix is not null
            Preconditions.checkNotNull(separator);
        }
        mNamespace = namespace;
        mPrefix = prefix;
        mSeparator = separator;
        mIdentifier = identifier;

        StringBuilder sb = new StringBuilder();
        if (mNamespace != null) {
            sb.append(mNamespace).append(":");
        }
        if (mPrefix != null) {
            sb.append(mPrefix).append(mSeparator);
        }
        sb.append(mIdentifier);

        mName = sb.toString();
    }

    public static TableName valueOf(@Nonnull String name) {
        String namespace = null;
        String prefix = null;
        int namespace_index = CharMatcher.is(':').indexIn(name);
        if (namespace_index > 0) {
            namespace = name.substring(0, namespace_index);
        }
        String remaining = name.substring(namespace_index + 1);
        int prefix_index = CharMatcher.is(TableName.DEFAULT_SEPARATOR).indexIn(remaining);
        if (prefix_index >= 0) {
            prefix = remaining.substring(0, prefix_index);
        }
        String identifier = remaining.substring(prefix_index + 1);
        return new TableName(namespace, prefix, TableName.DEFAULT_SEPARATOR, identifier);
    }

    /**
     * Returns the table namespace.
     *
     * @return the table namespace
     */
    public String getNamespace() {
        return mNamespace;
    }

    /**
     * Returns the table prefix.
     *
     * @return the table prefix
     */
    public String getPrefix() {
        return mPrefix;
    }

    /**
     * Returns the table prefix separator.
     *
     * @return the table prefix separator
     */
    public Character getSeparator() {
        return mSeparator;
    }

    /**
     * Returns the table identifier.
     *
     * @return the table identifier
     */
    public String getIdentifier() {
        return mIdentifier;
    }

    /**
     * Returns the HBase table full name.
     *
     * @return Plain text of the table name. e.g. TAS, Test_TAS or ETS:Test_TAS.
     */
    @Override
    public String toString() {
        return mName;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object otherObj) {
        if (otherObj == this) {
            return true;
        } else if (null == otherObj) {
            return false;
        } else if (!otherObj.getClass().equals(getClass())) {
            return false;
        }
        final TableName other = (TableName) otherObj;
        return other.toString().equals(this.toString());
    }

    public static class TableNameBuilder {
        private String mPrefix;
        private String mNamespace;
        private Character mSeparator = TableName.DEFAULT_SEPARATOR;
        private String mIdentifier;

        public static TableNameBuilder newBuilder() {
            return new TableNameBuilder();
        }

        public TableNameBuilder withNamespace(String namespace) {
            mNamespace = namespace;
            return this;
        }

        public TableNameBuilder withPrefix(String prefix) {
            mPrefix = prefix;
            return this;
        }

        public TableNameBuilder withSeparator(Character separator) {
            mSeparator = separator;
            return this;
        }

        public TableNameBuilder withIdentifier(String identifier) {
            mIdentifier = identifier;
            return this;
        }

        public TableName build() {
            return new TableName(mNamespace, mPrefix, mSeparator, mIdentifier);
        }
    }
}
